#include<intersection_remesh_and_cut.h>
#include<tool/libcell_tools_io.h>
#define quote lib_cell_quote
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C"{
#endif

static Int_RB_Tree* test_zkhy_layered_get_connected_cells(Mesh* m ,Int_RB_Tree*tree)
{
    Int_RB_Tree* re=(Int_RB_Tree*)malloc(sizeof(Int_RB_Tree));
    int_rb_tree_init(re);
    if(tree==NULL)
    {
        return re;
    }
    auto it1=tree->begin(tree);
    template_c* c=(template_c*)(*it1);
    Node* tempn=NULL;
    tempn=node_overlying(tempn,c);
    tree->erase(tree,c->id);
    re->insert(re,c->id,c);
    while(tempn!=NULL)
    {
        Node* tempn1=NULL;
        for(Node* nit=tempn;nit!=NULL;nit=(Node*)(nit->Next))
        {
            template_c* c2=(template_c*)(nit->value);
            for(auto it=m->chf_begin(m,*c2);it!=m->chf_end(m,*c2);it++)
            {
             
                template_c* c3=m->s_opposite_halfface(quote(it))->cell;
                if(c3==NULL||tree->find(tree,c3->id)==NULL)
                {
                    continue;
                }
                tempn1=node_overlying(tempn1,c3); 
                tree->erase(tree,c3->id);
                re->insert(re,c3->id,c3);
            }            
        }
        free_node(tempn);
        tempn=tempn1;        
    } 
 

    return re;

}
static void test_zkhy_layered_wirte_mesh(Mesh*nm,Int_RB_Tree*tree,const char * filename)
{
    Int_RB_Tree* t=(Int_RB_Tree*)malloc(sizeof(Int_RB_Tree));
    int_rb_tree_init(t);
    int i=0;
    Node* vs=NULL;
    for(auto it=tree->begin(tree);it.it!=NULL;it++ )
    {
        template_c* c=(template_c*)(*it);
        for(auto cv=nm->cv_begin(nm,*c);cv!=nm->cv_end(nm,*c);cv++)
        {
            template_v* v=(template_v*)quote(cv);
            if(t->find(t,v->id)==NULL)
            {
                int* value=(int*)malloc(sizeof(int));
                *value=i;
                t->insert(t,v->id,value);
                vs=node_pushback(vs,v);
               i++; 
            }

        }
    }


#ifdef _WIN32
    FILE* infile;
    fopen_s(&infile,filename,"w");
#else
    FILE *infile=fopen(filename,"w");
#endif 
    int len=tree->size;
    fprintf(infile, "OFF\n%d %d 0\n",i,len);
    //i=0;
    vs=node_reverse(vs);
    for(Node* nit=vs;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v* v=(template_v*)(nit->value);
        fprintf(infile, "%lf %lf %lf\n",v->point[0],v->point[1],v->point[2] );
        //i++;
    } 

    for(auto it=tree->begin(tree);it.it!=NULL;it++)
    {
        template_c* c=(template_c*)(*it);
        fprintf(infile,"%d ",c->vertices_size );
        for(auto cv=nm->cv_begin(nm,*c);cv!=nm->cv_end(nm,*c);cv++)
        {
            template_v* v=(template_v*)quote(cv);
            int* value=(int*)(t->find(t,v->id));
            // if(value==NULL)
            // {
            //     printf("value cuowu \n");
            // }
            i=*value;
            fprintf(infile , "%d ",i );
            //free(value); 
        }
        fprintf(infile, "\n" );
    }

    fclose(infile);
    for(auto it=t->begin(t);it.it!=NULL;it++)
    {
       free(it.it->data);
    } 
    int_rb_tree_free(t); 
    free_node(vs);
}

static Int_RB_Tree* test_zkhy_layered_get_cells_z(Mesh* m,float z,Int_RB_Tree* tree)
{
    Int_RB_Tree* re=(Int_RB_Tree*)malloc(sizeof(Int_RB_Tree));
    int_rb_tree_init(re);
    for(auto it=tree->begin(tree);it.it!=NULL;it++)
    {
        template_c* c=(template_c*)(*it);
        float cent=0;
        for(auto cv=m->cv_begin(m,*c);cv!=m->cv_end(m,*c);cv++)
        {
            cent+=quote(cv)->point[2];
        }
        cent=cent/3.0;

       // printf("%f %f\n",cent,z );
        // if(c==NULL)
        // {
        //     printf("cuowu c \n");
        // }
        if(cent>z)
        {
            re->insert(re,c->id,c);
        }
    } 
    for(auto it=re->begin(re);it.it!=NULL;it++)
    {
        template_c* c=(template_c*)(*it);
        tree->erase(tree,c->id); 
    }

    return re;

}
__declspec(dllexport) void test_zkhy_layered_split_one(const char *filename,float z)
{

char outfilename[]="quad.off";
#ifdef _WIN32
    FILE* infile;
    fopen_s(&infile,outfilename,"w");
#else
    FILE *infile=fopen(outfilename,"w");
#endif 
    fprintf(infile, "OFF\n4 2 0\n-400000 -400000 %f\n400000 -400000 %f\n400000 400000 %f\n-400000 400000 %f\n",z ,z ,z ,z );
    fprintf(infile, "3 0 1 3\n3 1 2 3");

    fclose(infile);
    Mesh mesh1,mesh2,mesh;
    Mesh_init(&mesh1);Mesh_init(&mesh2);Mesh_init(&mesh);
    _Read_(&mesh1,"quad.off");
    _Read_(&mesh2,filename);

    get_intersection_lines_of_two_meshs(&mesh1,&mesh2,&mesh);

    adjust_mesh_topology(&mesh);
    Mesh* nm=my_intersection_remesh(&mesh2,&mesh);
    my_intersection_cut(nm,&mesh);


    Int_RB_Tree* tree=int_rb_tree_copy(nm->cells);
    //test_zkhy_layered_wirte_mesh(nm,tree,"nm.off");

   //  printf("%d\n",tree->size );
   Int_RB_Tree* tree1= test_zkhy_layered_get_cells_z(nm,z,tree);
   // // Int_RB_Tree* tree1=test_zkhy_layered_get_connected_cells(nm,tree);

   test_zkhy_layered_wirte_mesh(nm,tree1,"up.off"); 

    test_zkhy_layered_wirte_mesh(nm,tree,"bo.off"); 
   //printf("%d %d\n",tree->size,tree1->size );
   int_rb_tree_free(tree1);


    int_rb_tree_free(tree);
    //mesh v prop 内存要清除
    Mesh_free(&mesh1);Mesh_free(&mesh2);Mesh_free(&mesh);
    Mesh_free(nm);
    remove("quad.off");
    //rename("bo.off","botom.off");

}
__declspec(dllexport) int test_zkhy_layered(const char *filename ,float * zz,int len)
{

    if(len<=2||zz==NULL)
    {
        return 0;
    } 

    test_zkhy_layered_split_one(filename,zz[1]);
    printf("zz1%lf\n",zz[1] );
    rename("bo.off","0.off");
    rename("up.off","1.off"); 

   // char f[25]={0};
   //      itoa(1,f,10);
   //      char we[]=".off";
   //      strcat(f,we); 
   //      printf("f %s\n",f );

    //test_zkhy_layered_split_one(f,zz[2]);
 
    for(int i=2;i<len-1;i++)
    {
        char f[25]={0};
        itoa(i-1,f,10);
        char we[]=".off";
        strcat(f,we);
        test_zkhy_layered_split_one(f,zz[i]);
        remove(f);
        rename("bo.off",f);
        char f1[25]={0};
        itoa(i,f1,10);
        strcat(f1,we);
        rename("up.off",f1);
    } 
    // for(int i=0;i<len-2;i++)
    // {
    //     char f[100]={0};
    //     strcat(f,dir);
    //     char f1[25]={0};
    //     itoa(i,f1,10);
    //     char we[]=".off";
    //     strcat(f1,we); 
    //     strcat(f,f1);
    //     rename(f1,f);
    //     printf(" %s %s\n",f1,f );
    // }


    //itoa();
    //rename("") 

    return 1; 


}




#ifdef __cplusplus
}
#endif

#endif